package com.gpframework.module.interceptor;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.Signature;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


@Aspect
@Component
public class DeInterceptor {

	private static final Logger log = LoggerFactory.getLogger(DeInterceptor.class);

    /**
     * 在方法执行之前和之后执行（计算执行时间）
     */
    @Around("@annotation(SystemLogAnnotation)")
    public Object interceptor(ProceedingJoinPoint point) throws Throwable {
        // Spring计时器StopWatch
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        // 1.获取请求路径
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = requestAttributes.getRequest();
        String url = httpServletRequest.getRequestURI();

        // 2.获取请求参数
        Object[] args = point.getArgs();
        String reqParam = null;
        String requestContentType = httpServletRequest.getContentType()== null ? "" : httpServletRequest.getContentType();
        // 不同请求类型使用不同的方法获取入参
            try{
                if (requestContentType.contains("application/json")){
                    // args数组里面存储的就是controller里方法里面的入参顺序参数，一般JSON格式入参就一个对象接收参数，那就取第0个，否则可以全部输出args
                    reqParam = JSON.toJSONString(args[0]);
                }else{
                    reqParam = JSON.toJSONString(httpServletRequest.getParameterMap());
                }
            }catch (Exception e){
                e.getStackTrace();
            }


        // 3.获取方法相关信息
        Signature signature = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        SystemLogAnnotation annotation = method.getAnnotation(SystemLogAnnotation.class);

        String methodStr = point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName();

        log.info("请求开始，请求路径：{},请求方法：{},请求方法说明：{},请求参数：{}",url,methodStr,annotation.value(),reqParam);

        // 4.获取响应数据
        Object result = point.proceed();

        stopWatch.stop();
        log.info("请求结束,耗时{}毫秒，响应参数：{}",stopWatch.getTime(),result);
        return result;
    }
}
